package cn.lingyangwl.agile.infra.gen.controller;

import cn.afterturn.easypoi.excel.ExcelImportUtil;
import cn.afterturn.easypoi.excel.entity.ExportParams;
import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.enmus.ExcelType;
import cn.hutool.core.io.resource.ResourceUtil;
import cn.lingyangwl.agile.file.excel.*;
import cn.lingyangwl.agile.infra.gen.model.entity.*;
import cn.lingyangwl.agile.infra.gen.model.rqrs.*;
import cn.lingyangwl.agile.infra.gen.service.*;
import cn.lingyangwl.agile.ram.*;
import cn.lingyangwl.framework.core.response.*;
import cn.lingyangwl.framework.security.xss.core.*;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.TypeReference;
import com.baomidou.mybatisplus.core.metadata.IPage;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import javax.validation.constraints.NotNull;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

/**
 * @author shenguangyang
 */
@Api(tags = "代码模板")
@RestController
@Validated
@RequestMapping("/codeTemplate")
@RequiredArgsConstructor
public class TemplateConfigController {
    private final TemplateConfigService templateConfigService;

    @ApiOperation(value = "导出代码模板")
    @RamResource(action = "lcp:template:exportXls", name = "低代码-导出代码模板", type = ActionType.READ)
    @GetMapping("/exportXls")
    public void exportXls(HttpServletResponse response, @Validated TemplateQueryReq rq) throws Exception {
        List<TemplateConfig> list = templateConfigService.list(rq);
        ExportParams params = new ExportParams();
        params.setType(ExcelType.HSSF);
        CusExcelExportUtil.exportExcel(response, params, "模板.xls", TemplateConfig.class, list);
    }

    @ApiOperation(value = "导入代码模板")
    @RamResource(action = "lcp:template:importExcel", name = "低代码-导入代码模板", type = ActionType.WRITE)
    @PostMapping("/importExcel")
    public Resp<?> importExcel(MultipartFile file,
                               @RequestParam(value = "groupId", required = false)
                               @NotNull(message = "请选择模板组") Long groupId) throws Exception {
        List<TemplateConfig> userList = ExcelImportUtil.importExcel(file.getInputStream(), TemplateConfig.class, new ImportParams());
        String message = templateConfigService.importExcel(userList, groupId, true);
        return Resp.ok(message);
    }

    @ApiOperation(value = "查询代码模板详情")
    @RamResource(action = "lcp:template:query", name = "低代码-查询代码模板", type = ActionType.READ)
    @GetMapping("/getTemplate")
    public Resp<TemplateConfig> get(@RequestParam("id") Long id) {
        return Resp.ok(templateConfigService.getById(id));
    }

    @ApiOperation(value = "查询代码模板列表")
    @RamResource(action = "lcp:template:query", name = "低代码-查询代码模板", type = ActionType.READ)
    @GetMapping("/listTemplateByGroupId")
    public Resp<List<TemplateConfigResp>> listByGroupId(@RequestParam("groupId") Long groupId) {
        return Resp.ok(templateConfigService.listByGroupId(groupId));
    }

    @ApiOperation(value = "分页查询代码模板列表")
    @RamResource(action = "lcp:template:query", name = "低代码-查询代码模板", type = ActionType.READ)
    @GetMapping("/pageTemplate")
    public Resp<IPage<TemplateConfig>> page(@Validated TemplateQueryReq req) {
        IPage<TemplateConfig> resp = templateConfigService.page(req);
        return Resp.ok(resp);
    }

    @ApiOperation(value = "更新代码模板")
    @XssCleanIgnore({"content"})
    @RamResource(action = "lcp:template:query", name = "低代码-更新代码模板", type = ActionType.WRITE)
    @PostMapping("/updateTemplate")
    public Resp<?> update(@RequestBody @Validated TemplateConfigReq req) {
        templateConfigService.updateById(req);
        return Resp.ok();
    }

    @ApiOperation(value = "删除代码模板")
    @RamResource(action = "lcp:template:query", name = "低代码-删除代码模板", type = ActionType.WRITE)
    @DeleteMapping("/deleteTemplate")
    public Resp<?> delete(@RequestBody TemplateConfig templateConfig) {
        templateConfigService.deleteById(templateConfig);
        return Resp.ok();
    }

    @ApiOperation(value = "批量删除代码模板")
    @RamResource(action = "lcp:template:query", name = "低代码-删除代码模板", type = ActionType.WRITE)
    @DeleteMapping("/batchDeleteTemplate")
    public Resp<?> deleteBatch(@RequestParam("ids") List<Long> ids) {
        templateConfigService.deleteBatchByIds(ids);
        return Resp.ok();
    }

    @ApiOperation(value = "保存代码模板")
    @RamResource(action = "lcp:template:save", name = "低代码-保存代码模板", type = ActionType.WRITE)
    @PostMapping("/saveTemplate")
    @XssCleanIgnore({"content"})
    public Resp<?> save(@RequestBody @Validated TemplateConfigReq req) {
        templateConfigService.save(req);
        return Resp.ok();
    }

    @ApiOperation(value = "拷贝代码模板")
    @RamResource(action = "lcp:template:save", name = "低代码-拷贝代码模板", type = ActionType.WRITE)
    @PostMapping("/copyTemplate")
    public Resp<?> copy(@RequestBody CopyTemplateReq req) {
        templateConfigService.copyById(req);
        return Resp.ok();
    }

    public List<VelocityVariableResp.Variable> readData(String fileName) {
        String content = ResourceUtil.readStr("json/velocity-variable/" + fileName + ".json", StandardCharsets.UTF_8);
        return JSON.parseObject(content, new TypeReference<List<VelocityVariableResp.Variable>>() {{}});
    }

    /**
     * 获取Velocity模板引擎变量
     */
    @GetMapping("/listVelocityVar")
    @ApiOperation(value = "查询代码模板变量")
    @RamResource(action = "lcp:template:listVelocityVar", name = "低代码-查询代码模板变量", type = ActionType.READ)
    public Resp<List<VelocityVariableResp>> listVelocityVar() {
        List<VelocityVariableResp> respList = new ArrayList<>();
        List<VelocityVariableResp.Variable> javaJsonData= readData("java");
        List<VelocityVariableResp.Variable> csharpData = readData("csharp");

        VelocityVariableResp javaResp = VelocityVariableResp.builder()
                .tab("Java变量").key("java").varList(javaJsonData).build();
        respList.add(javaResp);

        VelocityVariableResp csharpResp = VelocityVariableResp.builder()
                .tab("C#变量").key("C#").varList(csharpData).build();
        respList.add(csharpResp);
        return Resp.ok(respList);
    }

}
